﻿
using DADAL;
using System.IO.Ports;
using Modbus.Device;

namespace DABLL
{
    public class Index
    {
        #region 属性

        /// <summary>
        /// 设备
        /// </summary>
        private Device DeviceService = new Device();

        /// <summary>串口字典
        ///  Key->串口地址
        /// </summary>
        private Dictionary<string, SerialPort> SerialPortDic = new Dictionary<string, SerialPort> { };

        /// <summary>串口字典
        /// Key->设备编号
        /// </summary>
        private Dictionary<string, SerialPort> DeviceSerialPortDic = new Dictionary<string, SerialPort> { };

        /// <summary>点位字典
        /// 
        /// </summary>
        private Dictionary<string, DevicePointModel> DevicePointDic = new Dictionary<string, DevicePointModel> { };

        /// <summary>点位字典
        /// 
        /// </summary>
        private Dictionary<string, Dictionary<string, object>> MasterDic = new Dictionary<string, Dictionary<string, object>> { };

        /// <summary>界面点位字典
        /// 
        /// </summary>
        private Dictionary<string, string> FrormPointDic = new Dictionary<string, string> { };

        /// <summary>
        /// 点位数组
        /// </summary>
        private List<string> DevicePointList = new List<string>();

        #endregion

        #region 自定义方法

        /// <summary>
        /// 配置
        /// </summary>
        public void Setup()
        {
            LoadDeviceList();
        }

        /// <summary>设备列表
        /// 
        /// </summary>
        public void LoadDeviceList()
        {
            List<DeviceModel> list = SqlSugarHelper.Inquireable<DeviceModel>(null);
            foreach (DeviceModel item in list)
            {
                string deviceNumber = item.Number.ToString();
                string port_address = item.PortAddress; // 串口地址
                int baudRate = (int)item.Baudrate;   // 波特率
                var dataBits = 8;      // 数据位
                var stopBits = StopBits.One; // 停止位
                var parity = Parity.None;    // 校验位
                SerialPort serialPort = new SerialPort(port_address, baudRate, parity, dataBits, stopBits);
                if (!SerialPortDic.ContainsKey(port_address))
                {
                    Log.Debug(string.Format("【{0}】开始联接", port_address));
                    try
                    {
                        serialPort.Open();
                        if (serialPort.IsOpen)
                        {
                            Log.Info(string.Format("【{0}】连接成功✔", port_address));
                            DeviceSerialPortDic[deviceNumber] = serialPort;
                            SerialPortDic[port_address] = serialPort;
                        }
                        else
                        {
                            Log.Error(string.Format("【{0}】连接失败❌", port_address));
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(string.Format("【{0}】连接异常【{1}】❌", port_address, ex.Message));
                    }
                }
                else
                {
                    DeviceSerialPortDic[deviceNumber] = SerialPortDic[port_address];
                }
            }
            LoadDevicePointList();
        }

        /// <summary>设备点位列表
        /// 
        /// </summary>
        public void LoadDevicePointList()
        {
            List<DevicePointModel> list = SqlSugarHelper.Inquireable<DevicePointModel>(null);
            foreach (DevicePointModel item in list)
            {
                string deviceNumber = item.DeviceNumber.ToString();
                string itemNumber = item.Number.ToString();
                if (DeviceSerialPortDic.ContainsKey(deviceNumber))
                {
                    DevicePointDic[itemNumber] = item;
                }
            }

            LoadFormPointList();
        }

        /// <summary>界面点位列表
        /// 
        /// </summary>
        public void LoadFormPointList()
        {
            Dictionary<string, Object> where = new Dictionary<string, Object>();
            where["state"] = 1;
            List<FormPointModel> list = SqlSugarHelper.Inquireable<FormPointModel>(where);
            foreach (FormPointModel item in list)
            {
                if (DevicePointDic.ContainsKey(item.DevicePointNumber.ToString()))
                {
                    string form_point_name = string.Empty;
                    if (item.Name is not null)
                    {
                        form_point_name = item.Name;
                    }
                    FrormPointDic[form_point_name] = item.DevicePointNumber.ToString();
                }
            }
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Dictionary<string, object>? ReadRegisters(string key)
        {
            if (!FrormPointDic.ContainsKey(key))
            {
                //Log.Debug(string.Format("【{0}】配置不存在", key));
                return null;
            }
            Dictionary<string, object> back = new Dictionary<string, object>();
            DevicePointModel? model = DevicePointWithKey(key);
            if (model is not null)
            {
                SerialPort serialPort = DeviceSerialPortDic[model.DeviceNumber.ToString()];
                ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
                try
                {
                    string decrypt_slaveAddress = Encryption.DesDecrypt(model.DeviceAddress, SqlSugarHelper.EncryptionKey);

                    // 从设备地址
                    byte slaveAddress = (byte)Convert.ToInt16(decrypt_slaveAddress);

                    string decrypt_address = Encryption.DesDecrypt(model.Address, SqlSugarHelper.EncryptionKey);

                    ushort address = ushort.Parse(decrypt_address);
                    if (address > 0)
                    {
                        address = ushort.Parse((address).ToString());
                    }

                    master = SerialMasterTimeout(master);

                    Task<ushort[]>? ushortTask = null;

                    if (model.PointType == "Holding")
                    {

                        ushortTask = master.ReadHoldingRegistersAsync(slaveAddress, address, 1);
                    }
                    else if (model.PointType == "Input")
                    {
                        ushortTask = master.ReadInputRegistersAsync(slaveAddress, address, 1);
                    }

                    if (ushortTask is not null)
                    {
                        try
                        {
                            ushort[] shorts = ushortTask.Result;

                            back["data"] = shorts;
                            return back;
                        }
                        catch (Exception ex)
                        {
                            Log.Error(string.Format(" 【{0}】读取异常：{1}❌", model.Name, ex.Message));
                            return null;
                        }
                    }

                    Task<bool[]>? boolTask = null;
                    if (model.PointType == "DO")
                    {
                        boolTask = master.ReadCoilsAsync(slaveAddress, address, 1);
                    }
                    else if (model.PointType == "DI")
                    {
                        boolTask = master.ReadInputsAsync(slaveAddress, address, 1);
                    }
                    if (boolTask is not null)
                    {
                        try
                        {
                            bool[] shorts = boolTask.Result;

                            back["data"] = shorts;
                            return back;
                        }
                        catch (Exception ex)
                        {
                            Log.Error(string.Format(" 【{0}】读取异常：{1}❌", model.Name, ex.Message));
                            return null;
                        }
                    }

                    return null;
                }
                catch (Exception ex)
                {
                    Log.Error(string.Format(" 【{0}】点位设备地址解密错误{1}❌", model.Name, ex.Message));
                    return null;
                }
            }
            else
            {
                //Log.Error(string.Format("【{0}】设备点位不存在", key));
                return null;
            }
        }

        /// <summary>
        /// 获取DevicePointModel
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public DevicePointModel? DevicePointWithKey(string key)
        {
            string device_point_number = FrormPointDic[key];
            if (DevicePointDic.ContainsKey(device_point_number))
            {
                DevicePointModel model = DevicePointDic[device_point_number];
                return model;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// ModbusSerialMaster 超时
        /// </summary>
        /// <param name="master"></param>
        /// <returns></returns>
        private ModbusSerialMaster SerialMasterTimeout(ModbusSerialMaster master)
        {
            master.Transport.WriteTimeout = 1000;
            master.Transport.ReadTimeout = 1000;
            return master;
        }

        #endregion
    }
}
